"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.createInnerAudioContext = void 0;

var _utils = require("./utils");

function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }

function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }

function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }

function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }

function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }

function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }

/**
 * @typedef {object} InnerAudioContext
 * @property {string} src 音频资源的地址，用于直接播放。2.2.3 开始支持云文件ID
 * @property {number} [startTime=0] 开始播放的位置（单位：s），默认为 0
 * @property {boolean} [autoplay=false] 是否自动开始播放，默认为 false
 * @property {boolean} [loop=false] 是否循环播放，默认为 false
 * @property {boolean} [obeyMuteSwitch=true] 是否遵循系统静音开关，默认为 true。当此参数为 false 时，即使用户打开了静音开关，也能继续发出声音。从 2.3.0 版本开始此参数不生效，使用 wx.setInnerAudioOption 接口统一设置。
 * @property {number} [volume=1] 音量。范围 0~1。默认为 1
 * @property {number} duration 当前音频的长度（单位 s）。只有在当前有合法的 src 时返回（只读）
 * @property {number} currentTime 当前音频的播放位置（单位 s）。只有在当前有合法的 src 时返回，时间保留小数点后 6 位（只读）
 * @property {boolean} paused 当前是是否暂停或停止状态（只读）
 * @property {number} buffered 音频缓冲的时间点，仅保证当前播放时间点到此时间点内容已缓冲（只读）
 * @property {() => void} play() 播放
 * @property {() => void} pause() 暂停。暂停后的音频再播放会从暂停处开始播放
 * @property {() => void} stop() 停止。停止后的音频再播放会从头开始播放。
 * @property {(position: number) => void} seek(number position) 跳转到指定位置
 * @property {() => void} destroy() 销毁当前实例
 * @property {(callback: function) => void} offCanplay(function callback) 取消监听音频进入可以播放状态的事件
 * @property {(callback: function) => void} offEnded(function callback) 取消监听音频自然播放至结束的事件
 * @property {(callback: function) => void} offError(function callback) 取消监听音频播放错误事件
 * @property {(callback: function) => void} offPause(function callback) 取消监听音频暂停事件
 * @property {(callback: function) => void} offPlay(function callback) 取消监听音频播放事件
 * @property {(callback: function) => void} offSeeked(function callback) 取消监听音频完成跳转操作的事件
 * @property {(callback: function) => void} offSeeking(function callback) 取消监听音频进行跳转操作的事件
 * @property {(callback: function) => void} offStop(function callback) 取消监听音频停止事件
 * @property {(callback: function) => void} offTimeUpdate(function callback) 取消监听音频播放进度更新事件
 * @property {(callback: function) => void} offWaiting(function callback) 取消监听音频加载中事件
 * @property {(callback: function) => void} onCanplay(function callback) 监听音频进入可以播放状态的事件。但不保证后面可以流畅播放
 * @property {(callback: function) => void} onEnded(function callback) 监听音频自然播放至结束的事件
 * @property {(callback: function) => void} onError(function callback) 监听音频播放错误事件
 * @property {(callback: function) => void} onPause(function callback) 监听音频暂停事件
 * @property {(callback: function) => void} onPlay(function callback) 监听音频播放事件
 * @property {(callback: function) => void} onSeeked(function callback) 监听音频完成跳转操作的事件
 * @property {(callback: function) => void} onSeeking(function callback) 监听音频进行跳转操作的事件
 * @property {(callback: function) => void} onStop(function callback) 监听音频停止事件
 * @property {(callback: function) => void} onTimeUpdate(function callback) 监听音频播放进度更新事件
 * @property {(callback: function) => void} onWaiting(function callback) 监听音频加载中事件。当音频因为数据不足，需要停下来加载时会触发
 */

/**
 * 创建内部 audio 上下文 InnerAudioContext 对象。
 * @returns {InnerAudioContext}
 */
var createInnerAudioContext = function createInnerAudioContext() {
  /** @type {HTMLAudioElement} */
  var audioEl = new Audio();
  /** @type {InnerAudioContext} */

  var iac = {};
  var callbackManagers = {
    error: (0, _utils.createCallbackManager)(),
    stop: (0, _utils.createCallbackManager)()
  };

  iac.play = function () {
    return audioEl.play();
  };

  iac.pause = function () {
    return audioEl.pause();
  };

  iac.stop = function () {
    iac.pause();
    iac.seek(0);
    callbackManagers.stop.trigger();
  };

  iac.seek = function (position) {
    audioEl.currentTime = position;
  };
  /**
   * @todo destroy得并不干净
   */


  iac.destroy = function () {
    iac.stop(); // document.body.removeChild(audioEl)

    audioEl = null;
  };

  var simpleProperties = ['src', 'autoplay', 'loop', 'volume', 'duration', 'currentTime', 'buffered', 'paused'];
  simpleProperties.forEach(function (propertyName) {
    Object.defineProperty(iac, propertyName, {
      get: function get() {
        return audioEl ? audioEl[propertyName] : '';
      },
      set: function set(value) {
        audioEl[propertyName] = value;
      }
    });
  });
  Object.defineProperty(iac, 'startTime', {
    value: 0
  });
  Object.defineProperty(iac, 'obeyMuteSwitch', {
    value: true
  });
  var simpleEvents = ['Canplay', 'Ended', 'Pause', 'Play', 'Seeked', 'Seeking', 'TimeUpdate', 'Waiting', 'Error', 'Loadedmetadata'];
  var simpleListenerTuples = [['on', audioEl.addEventListener], ['off', audioEl.removeEventListener]];
  simpleEvents.forEach(function (eventName) {
    simpleListenerTuples.forEach(function (_ref) {
      var _ref2 = _slicedToArray(_ref, 2),
          eventNamePrefix = _ref2[0],
          listenerFunc = _ref2[1];

      Object.defineProperty(iac, "".concat(eventNamePrefix).concat(eventName), {
        get: function get() {
          return function (callback) {
            return listenerFunc.call(audioEl, eventName.toLowerCase(), callback);
          };
        }
      });
    });
  }); // 有问题的代码，error并不能正常触发
  // const customEvents = ['Stop', 'Error'];
  // const customListenerTuples = [
  //   ['on', 'add'],
  //   ['off', 'remove'],
  // ];
  // customEvents.forEach((eventName) => {
  //   customListenerTuples.forEach(([eventNamePrefix, actionName]) => {
  //     Object.defineProperty(iac, `${eventNamePrefix}${eventName}`, {
  //       get() {
  //         return callback => callbackManagers[eventName.toLowerCase()][actionName](callback);
  //       },
  //     });
  //   });
  // });

  return iac;
};

exports.createInnerAudioContext = createInnerAudioContext;